package org.mili.ticketeer.dao;

import org.mili.ticketeer.dao.query.v2.QueryBuilder;
import org.mili.ticketeer.dto.Action;
import org.mili.ticketeer.dto.Contact;
import org.mili.ticketeer.dto.ContactAction;
import org.mili.ticketeer.dto.Identifieable;
import org.mili.ticketeer.dto.Ticket;
import org.mili.ticketeer.util.Lambda;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;

public class ActionDao extends AbstractDao {

    public ActionDao() {
        super(Action.UniqueFields.values(), Action.Fields.values(), Action.TABLE);
    }

    public List<Action> getActions() throws DaoException {
        return read(new RowTransformer<Action>() {
            @Override
            public Action transform(ResultSet resultSet) throws SQLException {
                Action action = new Action();
                action.setId(resultSet.getInt(Identifieable.Fields.ID.name()));
                action.setTicket(resultSet.getInt(Action.Fields.TICKET.name()));
                action.setComment(resultSet.getString(Action.Fields.COMMENT.name()));
                action.setTitle(resultSet.getString(Action.Fields.TITLE.name()));
                action.setDate(resultSet.getTimestamp(Action.Fields.DATE.name()));
                return action;
            }
        });
    }

    public ModificationResult write(final Action action) throws DaoException {
        return createOrUpdate(action);
    }

    public Boolean assign(final Contact contact, final Action action) throws DaoException {
        return doInDao(new Lambda<Boolean>() {
            @Override
            public Boolean exec(Object... params) throws SQLException {
                return update("insert into `contact_action` (`contact`, `action`) values(?, ?);", contact.getId(), action.getId()) == 1;
            }
        });
    }

    public List<Action> getActionsFor(final Ticket ticket) throws DaoException {
        return read(new RowTransformer<Action>() {
                @Override
                public Action transform(ResultSet resultSet) throws SQLException {
                    Action action = new Action();
                    action.setId(resultSet.getInt(Identifieable.Fields.ID.name()));
                    action.setTicket(resultSet.getInt(Action.Fields.TICKET.name()));
                    action.setComment(resultSet.getString(Action.Fields.COMMENT.name()));
                    action.setTitle(resultSet.getString(Action.Fields.TITLE.name()));
                    action.setDate(resultSet.getTimestamp(Action.Fields.DATE.name()));
                    return action;
                }
            }, QueryBuilder.createQueryBuilder()
                    .select()
                    .fields(Identifieable.Fields.ID, Action.Fields.values())
                    .from(Action.TABLE)
                    .where()
                    .eq(Action.Fields.TICKET, ticket.getId())
                    .orderBy()
                    .asc(Action.Fields.DATE)
                    .build()
            );
    }

    public List<Contact> getAssignmentsFor(final Action action) throws DaoException {
        final List<Integer> contacts = read(
                new RowTransformer() {
                    @Override
                    public Integer transform(ResultSet resultSet) throws SQLException {
                        return resultSet.getInt(ContactAction.Fields.CONTACT.name());
                    }
                },
                QueryBuilder.createQueryBuilder()
                    .select()
                    .fields(ContactAction.Fields.values())
                    .from(ContactAction.TABLE)
                    .where()
                    .eq(ContactAction.Fields.ACTION, action.getId())
                    .build()
        );

        if (contacts.size() == 0) {
            return Collections.emptyList();
        }

        return read(new ContactDao.ContactRowTransformer(),
                    QueryBuilder.createQueryBuilder()
                        .select()
                        .fields(Identifieable.Fields.ID, Contact.Fields.values())
                        .from(Contact.TABLE)
                        .where()
                        .in(Identifieable.Fields.ID, contacts)
                        .build()
        );
    }
}
